#!/bin/sh -eu

TEST="$1"

HEADER='#include <test-dept.h>

typedef void (*test_dept_test_function)();
typedef void (*test_dept_prepost_function)();

typedef struct {
  test_dept_test_function function;
  char* name;
} test_dept_test_function_data;
'

FOOTER='int main(int argc, char *argv[]) {
  if (argc == 1) {
    int i = 0;
    while (i < number_of_test_functions)
      printf("%s\\n", test_functions[i++].name);
  }
  int test_no = 1;
  for (test_no; test_no < argc; test_no++) {
    char* test_fun_name = argv[test_no];
    int test_fun = 0;
    for (; test_fun < number_of_test_functions; test_fun++)
      if (0 == strcmp(test_fun_name, test_functions[test_fun].name))
        break;
    if (test_fun < 0 || test_fun >= number_of_test_functions) {
      fprintf(stderr, "No test named %s!\\n", test_fun_name);
      test_dept_test_failures += 1;
      continue;
    }
    test_dept_test_function_data current = test_functions[test_fun];
    printf("%s:\\n", current.name);
    fflush(stdout);
    if (setup_function)
      (*setup_function)();
    (*current.function)();
    if (teardown_function)
      (*teardown_function)();
  }
  return test_dept_test_failures;
}
'

echo "${HEADER}"
nm -p $TEST | awk '
BEGIN { no_tests = 0; setup = "NULL"; teardown = "NULL" }
/ T test_/ { tests[$3]; no_tests = no_tests + 1 }
/ T set_*up$/ { setup = $3 }
/ T tear_*down$/ { teardown = $3 }
END {
  for (test in tests) {
    print "void " test "();"
  }
  if (setup != "NULL") {
    print "void " setup "();";
    setup = "&" setup;
  }
  if (teardown != "NULL") {
    print "void " teardown "();";
    teardown = "&" teardown;
  }

  print "test_dept_prepost_function setup_function = " setup ";"
  print "test_dept_prepost_function teardown_function = " teardown ";"
  print "test_dept_test_function_data test_functions[] = {"
  for (test in tests) {
    print "  {&" test ", \"" test "\"},"
  }
  print "};"
  print "int number_of_test_functions = " no_tests ";"
}
'
echo "${FOOTER}"
